/* libspectrum.h: the library for dealing with ZX Spectrum emulator files
   Copyright (c) 2001-2003 Philip Kendall, Darren Salt

   $Id: libspectrum.h.in,v 1.101.2.1 2004/01/26 22:41:25 pak21 Exp $

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

   Author contact information:

   E-mail: pak21-fuse@srcf.ucam.org
   Postal address: 15 Crescent Road, Wokingham, Berks, RG40 2DB, England

*/

/* NB: This file is autogenerated from libspectrum.h.in. Do not edit
   unless you know what you're doing */

#ifndef LIBSPECTRUM_LIBSPECTRUM_H
#define LIBSPECTRUM_LIBSPECTRUM_H

#ifdef __cplusplus
extern "C" {
#endif				/* #ifdef __cplusplus */

#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>

//#include <gcrypt.h>

/* Standard typedefs */
#include <stdint.h>

typedef  uint8_t libspectrum_byte;
typedef   int8_t libspectrum_signed_byte;
typedef uint16_t libspectrum_word;
typedef  int16_t libspectrum_signed_word;
typedef uint32_t libspectrum_dword;
typedef  int32_t libspectrum_signed_dword;
typedef uint64_t libspectrum_qword;
typedef  int64_t libspectrum_signed_qword;

/* glib replacement (if necessary) */
typedef int gint;
typedef unsigned int guint;
typedef const void * gconstpointer;
typedef void * gpointer;

typedef struct _GSList GSList;

struct _GSList {
    gpointer data;
    GSList *next;
};

typedef void		(*GFunc)		(gpointer	data,
						 gpointer	user_data);

typedef gint		(*GCompareFunc)		(gconstpointer	a,
						 gconstpointer	b);

GSList* g_slist_insert	(GSList		*list,
			 gpointer	 data,
			 gint		 position);

GSList* g_slist_insert_sorted	(GSList		*list,
				 gpointer	 data,
				 GCompareFunc	 func);

GSList* g_slist_append		(GSList		*list,
				 gpointer	 data);

GSList* g_slist_prepend	(GSList		*list,
				 gpointer	 data);

GSList* g_slist_delete_link	(GSList		*list,
				 GSList		*link);
				 
GSList* g_slist_remove		(GSList		*list,
				 gpointer	 data);

void	g_slist_foreach		(GSList		*list,
				 GFunc		 func,
				 gpointer	 user_data);

void	g_slist_free		(GSList		*list);

GSList* g_slist_nth		(GSList		*list,
				 guint		n);

GSList* g_slist_find_custom	(GSList		*list,
				 gpointer	data,
				 GCompareFunc	func );

gint	g_slist_position	(GSList		*list,
				 GSList		*llink);

/*
 * General libspectrum routines
 */

/* Error handling */

/* The various errors which can occur */
typedef enum libspectrum_error {

  LIBSPECTRUM_ERROR_NONE = 0,

  LIBSPECTRUM_ERROR_WARNING,

  LIBSPECTRUM_ERROR_MEMORY,
  LIBSPECTRUM_ERROR_UNKNOWN,
  LIBSPECTRUM_ERROR_CORRUPT,
  LIBSPECTRUM_ERROR_SIGNATURE,
  LIBSPECTRUM_ERROR_SLT,	/* .slt data found at end of a .z80 file */
  LIBSPECTRUM_ERROR_INVALID,	/* Invalid parameter supplied */

  LIBSPECTRUM_ERROR_LOGIC = -1,

} libspectrum_error;

/* Initialisation */

libspectrum_error libspectrum_init( void );

/* Version checking */

int libspectrum_check_version( const char *version );
const char  *libspectrum_version( void );
const char  *libspectrum_gcrypt_version( void );

/* Error handling */
typedef libspectrum_error
(*libspectrum_error_function_t)( libspectrum_error error,
				 const char *format, va_list ap );

extern libspectrum_error_function_t libspectrum_error_function;

libspectrum_error
libspectrum_default_error_function( libspectrum_error error,
				    const char *format, va_list ap );

/* Attempt to identify a given file */

/* Various types of file we might manage to identify */
typedef enum libspectrum_id_t {

  /* These types present in all versions of libspectrum */

  LIBSPECTRUM_ID_UNKNOWN = 0,		/* Unidentified file */
  LIBSPECTRUM_ID_RECORDING_RZX,		/* RZX input recording */
  LIBSPECTRUM_ID_SNAPSHOT_SNA,		/* .sna snapshot */
  LIBSPECTRUM_ID_SNAPSHOT_Z80,		/* .z80 snapshot */
  LIBSPECTRUM_ID_TAPE_TAP,		/* Z80-style .tap tape image */
  LIBSPECTRUM_ID_TAPE_TZX,		/* TZX tape image */

  /* Below here, present only in 0.1.1 and later */

  LIBSPECTRUM_ID_DISK_DSK,		/* .dsk +3 disk image */
  LIBSPECTRUM_ID_DISK_SCL,		/* .scl TR-DOS disk image */
  LIBSPECTRUM_ID_DISK_TRD,		/* .trd TR-DOS disk image */
  LIBSPECTRUM_ID_CARTRIDGE_DCK,		/* .dck Timex cartridge image */

  /* Below here, present only in 0.2.0 and later */

  LIBSPECTRUM_ID_TAPE_WARAJEVO,		/* Warajevo-style .tap tape image */ 

  LIBSPECTRUM_ID_SNAPSHOT_PLUSD,	/* DISCiPLE/+D snapshot */
  LIBSPECTRUM_ID_SNAPSHOT_SP,		/* .sp snapshot */
  LIBSPECTRUM_ID_SNAPSHOT_SNP,		/* .snp snapshot */
  LIBSPECTRUM_ID_SNAPSHOT_ZXS,		/* .zxs snapshot (zx32) */
  LIBSPECTRUM_ID_SNAPSHOT_SZX,		/* .szx snapshot (Spectaculator) */

  /* Below here, present only in 0.2.1 and later */

  LIBSPECTRUM_ID_COMPRESSED_BZ2,	/* bzip2 compressed file */
  LIBSPECTRUM_ID_COMPRESSED_GZ,		/* gzip compressed file */

  /* Below here, present only in 0.2.2 and later */

  LIBSPECTRUM_ID_HARDDISK_HDF,		/* .hdf hard disk image */
  LIBSPECTRUM_ID_CARTRIDGE_IF2,		/* .rom Interface II cartridge image */

  /* Below here, present only in 0.3.0 and later */

  LIBSPECTRUM_ID_MICRODRIVE_MDR,	/* .mdr microdrive cartridge */
  LIBSPECTRUM_ID_TAPE_CSW,		/* .csw tape image */
  LIBSPECTRUM_ID_TAPE_Z80EM,		/* Z80Em tape image */

  /* Below here, present only in 0.4.0 and later */
  LIBSPECTRUM_ID_TAPE_WAV,		/* .wav tape image */
  LIBSPECTRUM_ID_TAPE_SPC,		/* SP-style .spc tape image */
  LIBSPECTRUM_ID_TAPE_STA,		/* Speculator-style .sta tape image */
  LIBSPECTRUM_ID_TAPE_LTP,		/* Nuclear ZX-style .ltp tape image */
  LIBSPECTRUM_ID_COMPRESSED_XFD,	/* xfdmaster (Amiga) compressed file */
  LIBSPECTRUM_ID_DISK_IMG,		/* .img DISCiPLE/+D disk image */
  LIBSPECTRUM_ID_DISK_MGT,		/* .mgt DISCiPLE/+D disk image */

} libspectrum_id_t;

/* And 'classes' of file */
typedef enum libspectrum_class_t {

  LIBSPECTRUM_CLASS_UNKNOWN,

  LIBSPECTRUM_CLASS_CARTRIDGE_TIMEX,	/* Timex cartridges */
  LIBSPECTRUM_CLASS_DISK_PLUS3,		/* +3 disk */
  LIBSPECTRUM_CLASS_DISK_TRDOS,		/* TR-DOS disk */
  LIBSPECTRUM_CLASS_RECORDING,		/* Input recording */
  LIBSPECTRUM_CLASS_SNAPSHOT,		/* Snapshot */
  LIBSPECTRUM_CLASS_TAPE,		/* Tape */

  /* Below here, present only in 0.2.1 and later */

  LIBSPECTRUM_CLASS_COMPRESSED,		/* A compressed file */

  /* Below here, present only in 0.2.2 and later */

  LIBSPECTRUM_CLASS_HARDDISK,		/* A hard disk image */
  LIBSPECTRUM_CLASS_CARTRIDGE_IF2,	/* Interface II cartridges */

  /* Below here, present only in 0.3.0 and later */

  LIBSPECTRUM_CLASS_MICRODRIVE,		/* Microdrive cartridges */

  /* Below here, present only in 0.4.0 and later */

  LIBSPECTRUM_CLASS_DISK_PLUSD,		/* DISCiPLE/+D disk image */

} libspectrum_class_t;

libspectrum_error
libspectrum_identify_file( libspectrum_id_t *type, const char *filename,
                           const unsigned char *buffer, size_t length );

libspectrum_error
libspectrum_identify_file_with_class(
  libspectrum_id_t *type, libspectrum_class_t *libspectrum_class,
  const char *filename, const unsigned char *buffer, size_t length );

libspectrum_error
libspectrum_identify_file_raw( libspectrum_id_t *type, const char *filename,
			       const unsigned char *buffer, size_t length );

libspectrum_error
libspectrum_identify_class( libspectrum_class_t *libspectrum_class,
                            libspectrum_id_t type );

/* Different Spectrum variants and their capabilities */

/* The machine types we can handle */
typedef enum libspectrum_machine {

  LIBSPECTRUM_MACHINE_48,
  LIBSPECTRUM_MACHINE_TC2048,
  LIBSPECTRUM_MACHINE_128,
  LIBSPECTRUM_MACHINE_PLUS2,
  LIBSPECTRUM_MACHINE_PENT,
  LIBSPECTRUM_MACHINE_PLUS2A,
  LIBSPECTRUM_MACHINE_PLUS3,

  /* Used by libspectrum_tape_guess_hardware if we can't work out what
     hardware should be used */
  LIBSPECTRUM_MACHINE_UNKNOWN,

  LIBSPECTRUM_MACHINE_16,
  LIBSPECTRUM_MACHINE_TC2068,

} libspectrum_machine;

/*
 * Tape handling routines
 */

/* The various types of block available */
typedef enum libspectrum_tape_type {

  /* Values must be the same as used in the .tzx format */

  LIBSPECTRUM_TAPE_BLOCK_ROM = 0x10,
  LIBSPECTRUM_TAPE_BLOCK_TURBO,
  LIBSPECTRUM_TAPE_BLOCK_PURE_TONE,
  LIBSPECTRUM_TAPE_BLOCK_PULSES,
  LIBSPECTRUM_TAPE_BLOCK_PURE_DATA,
  LIBSPECTRUM_TAPE_BLOCK_RAW_DATA,

  LIBSPECTRUM_TAPE_BLOCK_GENERALISED_DATA = 0x19,

  LIBSPECTRUM_TAPE_BLOCK_PAUSE = 0x20,
  LIBSPECTRUM_TAPE_BLOCK_GROUP_START,
  LIBSPECTRUM_TAPE_BLOCK_GROUP_END,
  LIBSPECTRUM_TAPE_BLOCK_JUMP,
  LIBSPECTRUM_TAPE_BLOCK_LOOP_START,
  LIBSPECTRUM_TAPE_BLOCK_LOOP_END,

  LIBSPECTRUM_TAPE_BLOCK_SELECT = 0x28,

  LIBSPECTRUM_TAPE_BLOCK_STOP48 = 0x2a,

  LIBSPECTRUM_TAPE_BLOCK_COMMENT = 0x30,
  LIBSPECTRUM_TAPE_BLOCK_MESSAGE,
  LIBSPECTRUM_TAPE_BLOCK_ARCHIVE_INFO,
  LIBSPECTRUM_TAPE_BLOCK_HARDWARE,

  LIBSPECTRUM_TAPE_BLOCK_CUSTOM = 0x35,

  LIBSPECTRUM_TAPE_BLOCK_CONCAT = 0x5a,

  /* Past here are block types not in the .tzx format */

  LIBSPECTRUM_TAPE_BLOCK_RLE_PULSE = 0x100,

} libspectrum_tape_type;

typedef struct libspectrum_tape_block libspectrum_tape_block;
typedef struct libspectrum_tape_block_state libspectrum_tape_block_state;
typedef struct libspectrum_tape_generalised_data_symbol_table libspectrum_tape_generalised_data_symbol_table;

/* Something to step through all the blocks in a tape */
typedef struct _GSList *libspectrum_tape_iterator;

/* Some flags */
extern const int  LIBSPECTRUM_TAPE_FLAGS_BLOCK;  /* End of block */
extern const int  LIBSPECTRUM_TAPE_FLAGS_STOP;	  /* Stop tape */
extern const int  LIBSPECTRUM_TAPE_FLAGS_STOP48; /* Stop tape if in 48K mode */
extern const int  LIBSPECTRUM_TAPE_FLAGS_NO_EDGE; /* Edge isn't really an edge */
extern const int  LIBSPECTRUM_TAPE_FLAGS_LEVEL_LOW; /* Set level low */
extern const int  LIBSPECTRUM_TAPE_FLAGS_LEVEL_HIGH; /* Set level high */

/* The states which a block can be in */
typedef enum libspectrum_tape_state_type {

  LIBSPECTRUM_TAPE_STATE_INVALID = 0,

  LIBSPECTRUM_TAPE_STATE_PILOT,	/* Pilot pulses */
  LIBSPECTRUM_TAPE_STATE_SYNC1,	/* First sync pulse */
  LIBSPECTRUM_TAPE_STATE_SYNC2,	/* Second sync pulse */
  LIBSPECTRUM_TAPE_STATE_DATA1,	/* First edge of a data bit */
  LIBSPECTRUM_TAPE_STATE_DATA2,	/* Second edge of a data bit */
  LIBSPECTRUM_TAPE_STATE_PAUSE,	/* The pause at the end of a block */

} libspectrum_tape_state_type;

/* Routines to manipulate tape blocks */
libspectrum_error 
libspectrum_tape_block_alloc( libspectrum_tape_block **block,
			      libspectrum_tape_type type );
libspectrum_error 
libspectrum_tape_block_free( libspectrum_tape_block *block );
libspectrum_tape_type 
libspectrum_tape_block_type( libspectrum_tape_block *block );
libspectrum_error 
libspectrum_tape_block_set_type( libspectrum_tape_block *block,
				 libspectrum_tape_type type );

libspectrum_error 
libspectrum_tape_block_init( libspectrum_tape_block *block,
                             libspectrum_tape_block_state *state );

libspectrum_error 
libspectrum_tape_block_description( char *buffer, size_t length,
	                            libspectrum_tape_block *block );

int 
libspectrum_tape_block_metadata( libspectrum_tape_block *block );


//REVISAR
/* Accessor functions */
libspectrum_dword libspectrum_tape_block_bit_length( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_bit_length( libspectrum_tape_block *block, libspectrum_dword bit_length );
libspectrum_dword libspectrum_tape_block_bit0_length( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_bit0_length( libspectrum_tape_block *block, libspectrum_dword bit0_length );
libspectrum_dword libspectrum_tape_block_bit1_length( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_bit1_length( libspectrum_tape_block *block, libspectrum_dword bit1_length );
size_t libspectrum_tape_block_bits_in_last_byte( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_bits_in_last_byte( libspectrum_tape_block *block, size_t bits_in_last_byte );
size_t libspectrum_tape_block_count( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_count( libspectrum_tape_block *block, size_t count );
libspectrum_byte* libspectrum_tape_block_data( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_data( libspectrum_tape_block *block, libspectrum_byte* data );
size_t libspectrum_tape_block_data_length( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_data_length( libspectrum_tape_block *block, size_t data_length );
int libspectrum_tape_block_ids( libspectrum_tape_block *block, size_t idx );
libspectrum_error libspectrum_tape_block_set_ids( libspectrum_tape_block *block, int *ids );
int libspectrum_tape_block_offset( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_offset( libspectrum_tape_block *block, int offset );
int libspectrum_tape_block_offsets( libspectrum_tape_block *block, size_t idx );
libspectrum_error libspectrum_tape_block_set_offsets( libspectrum_tape_block *block, int *offsets );
libspectrum_dword libspectrum_tape_block_pause( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_pause( libspectrum_tape_block *block, libspectrum_dword pause );
libspectrum_dword libspectrum_tape_block_pilot_length( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_pilot_length( libspectrum_tape_block *block, libspectrum_dword pilot_length );
size_t libspectrum_tape_block_pilot_pulses( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_pilot_pulses( libspectrum_tape_block *block, size_t pilot_pulses );
libspectrum_dword libspectrum_tape_block_pulse_length( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_pulse_length( libspectrum_tape_block *block, libspectrum_dword pulse_length );
libspectrum_dword libspectrum_tape_block_pulse_lengths( libspectrum_tape_block *block, size_t idx );
libspectrum_error libspectrum_tape_block_set_pulse_lengths( libspectrum_tape_block *block, libspectrum_dword *pulse_lengths );
//libspectrum_tape_state_type libspectrum_tape_block_state( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_state( libspectrum_tape_block *block, libspectrum_tape_state_type state );
libspectrum_dword libspectrum_tape_block_sync1_length( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_sync1_length( libspectrum_tape_block *block, libspectrum_dword sync1_length );
libspectrum_dword libspectrum_tape_block_sync2_length( libspectrum_tape_block *block );
libspectrum_error libspectrum_tape_block_set_sync2_length( libspectrum_tape_block *block, libspectrum_dword sync2_length );
char* libspectrum_tape_block_text( libspectrum_tape_block *block );
//char* libspectrum_tape_block_texts( libspectrum_tape_block *block, size_t index );
//libspectrum_byte* libspectrum_tape_block_texts( libspectrum_tape_block *block, size_t idx );
libspectrum_error libspectrum_tape_block_set_texts( libspectrum_tape_block *block, char* *texts );
//libspectrum_error libspectrum_tape_block_set_texts( libspectrum_tape_block *block, libspectrum_byte* *texts );
int libspectrum_tape_block_types( libspectrum_tape_block *block, size_t idx );
libspectrum_error libspectrum_tape_block_set_types( libspectrum_tape_block *block, int *types );
int libspectrum_tape_block_values( libspectrum_tape_block *block, size_t idx );
libspectrum_error libspectrum_tape_block_set_values( libspectrum_tape_block *block, int *values );

/* A linked list of tape blocks */
typedef struct libspectrum_tape libspectrum_tape;

libspectrum_error  libspectrum_tape_alloc( libspectrum_tape **tape );
libspectrum_error  libspectrum_tape_clear( libspectrum_tape *tape );
libspectrum_error  libspectrum_tape_free( libspectrum_tape *tape );

/* Read in a tape file, optionally guessing what sort of file it is */
libspectrum_error 
libspectrum_tape_read( libspectrum_tape *tape, const libspectrum_byte *buffer,
		       size_t length, libspectrum_id_t type,
		       const char *filename );

/* Write a tape file */
libspectrum_error 
libspectrum_tape_write( libspectrum_byte **buffer, size_t *length,
			libspectrum_tape *tape, libspectrum_id_t type );

/* Does this tape structure actually contain a tape? */
int  libspectrum_tape_present( const libspectrum_tape *tape );

libspectrum_error 
libspectrum_tape_get_next_edge( libspectrum_dword *tstates, int *flags,
	                        libspectrum_tape *tape );

/* Get the current block from the tape */
libspectrum_tape_block  *
libspectrum_tape_current_block( libspectrum_tape *tape );

/* Get the state of the active block on the tape */
libspectrum_tape_state_type 
libspectrum_tape_state( libspectrum_tape *tape );

/* Set the state of the active block on the tape */
libspectrum_error 
libspectrum_tape_set_state( libspectrum_tape *tape,
                            libspectrum_tape_state_type state );

/* Peek at the next block on the tape */
libspectrum_tape_block  *
libspectrum_tape_peek_next_block( libspectrum_tape *tape );

/* Cause the next block on the tape to be active, initialise it
   and return it */
libspectrum_tape_block  *
libspectrum_tape_select_next_block( libspectrum_tape *tape );

/* Get the position on the tape of the current block */
libspectrum_error 
libspectrum_tape_position( int *n, libspectrum_tape *tape );

/* Select the nth block on the tape */
libspectrum_error 
libspectrum_tape_nth_block( libspectrum_tape *tape, int n );

/* Append a block to the current tape */
libspectrum_error 
libspectrum_tape_append_block( libspectrum_tape *tape,
			       libspectrum_tape_block *block );

libspectrum_error
libspectrum_tape_remove_block( libspectrum_tape *tape,
			       libspectrum_tape_iterator it );

libspectrum_error
libspectrum_tape_insert_block( libspectrum_tape *tape,
			       libspectrum_tape_block *block,
			       size_t position );

/*** Routines for iterating through a tape ***/

libspectrum_tape_block  *
libspectrum_tape_iterator_init( libspectrum_tape_iterator *iterator,
				libspectrum_tape *tape );

libspectrum_tape_block  *
libspectrum_tape_iterator_current( libspectrum_tape_iterator iterator );

libspectrum_tape_block  *
libspectrum_tape_iterator_next( libspectrum_tape_iterator *iterator );

/*** Routines for handling the TZX generalised data block symbol table
     structure ***/

typedef enum libspectrum_tape_generalised_data_symbol_edge_type {

  LIBSPECTRUM_TAPE_GENERALISED_DATA_SYMBOL_EDGE = 0x00,
  LIBSPECTRUM_TAPE_GENERALISED_DATA_SYMBOL_NO_EDGE,
  LIBSPECTRUM_TAPE_GENERALISED_DATA_SYMBOL_LOW,
  LIBSPECTRUM_TAPE_GENERALISED_DATA_SYMBOL_HIGH,

} libspectrum_tape_generalised_data_symbol_edge_type;

typedef struct libspectrum_tape_generalised_data_symbol libspectrum_tape_generalised_data_symbol;

libspectrum_dword  libspectrum_tape_generalised_data_symbol_table_symbols_in_block( const libspectrum_tape_generalised_data_symbol_table *table );
libspectrum_byte  libspectrum_tape_generalised_data_symbol_table_max_pulses( const libspectrum_tape_generalised_data_symbol_table *table );
libspectrum_word  libspectrum_tape_generalised_data_symbol_table_symbols_in_table( const libspectrum_tape_generalised_data_symbol_table *table );
libspectrum_tape_generalised_data_symbol*  libspectrum_tape_generalised_data_symbol_table_symbol( const libspectrum_tape_generalised_data_symbol_table *table, size_t which );	

libspectrum_tape_generalised_data_symbol_edge_type  libspectrum_tape_generalised_data_symbol_type( const libspectrum_tape_generalised_data_symbol *symbol );
libspectrum_word  libspectrum_tape_generalised_data_symbol_pulse( const libspectrum_tape_generalised_data_symbol *symbol, size_t which );



#ifdef __cplusplus
};
#endif				/* #ifdef __cplusplus */

#endif				/* #ifndef LIBSPECTRUM_LIBSPECTRUM_H */
